package com.lucenten.collect.gnss.handler.tools;

import cn.quevo.common.lang.DateFormatUtils;
import cn.quevo.common.lang.DateUtils;
import cn.quevo.common.lang.NumberUtils;
import cn.quevo.common.lang.StringUtils;
import com.lucenten.collect.Context;
import com.lucenten.collect.gnss.entity.GnssFile;
import com.lucenten.collect.gnss.entity.SatelliteStation;
import com.lucenten.collect.gnss.handler.AbstractGnssHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
public class TecpTeclToolBak {

    public static void merge(GnssFile gnssFile, Path oFile) {
        Path path = oFile.getParent();
        String ofileName = oFile.getFileName().normalize().toString();
        // 站点名称
        String stationName = ofileName.substring(0, 4);
        // 如果是错误站点，或者站点不在数据库，则忽略
        if (Context.ERROR_STATION.contains(stationName)) {
            return;
        }
        //N文件文件名
        String navfileName = ofileName.substring(0, ofileName.length() - 1) + "n";
        //G文件文件名
        String gfileName = ofileName.substring(0, ofileName.length() - 1) + "g";
        //c文件文件名
        String cfileName = ofileName.substring(0, ofileName.length() - 1) + "c";


    }

    private void write(Path gnsFile, Path tecpFile) {

    }

    /**
     * 判定版本类型
     *
     * @param file
     * @param version
     * @return
     */
    private boolean isVersion(Path file, String version) {
        try {
            List<String> lines = Files.readAllLines(file);
            return !StringUtils.isEmpty(lines) && lines.get(0).contains(version);
        } catch (IOException e) {
            return false;
        }
    }

    public List<String> getTecpTecl(GnssFile gnssFile, Path navFile, String navVersion, Path oFile, String oVersion) {
        SatelliteStation station = gnssFile.getReStations().get(gnssFile.getStationId()+","+gnssFile.getStationName());
        List<String> list = new ArrayList<>();
        List<Integer> starList = new ArrayList<>();
        Double lon = station.getLongitude();
        Double lat = station.getLatitude();
        Double height = station.getAntennaHeight();
        double x = 0, y = 0, z = 0;
        String hour = NumberUtils.format(gnssFile.getHoure(),"00");
        int obsTypeNum = 0;   //观测类型数量
        List<String> obsTypeList = new ArrayList<>();//观测类型
        int weekseconds = 0;
        try {
            int index = 0;
            String line = "";
            if ("2".equalsIgnoreCase(oVersion)) {
                List<String> lines = Files.readAllLines(oFile);
                for (; index < lines.size(); index++) {
                    line = lines.get(index);
                    if (line.contains("APPROX POSITION XYZ")) {
                        x = Double.parseDouble(line.substring(0, 14).trim());
                        y = Double.parseDouble(line.substring(14, 28).trim());
                        z = Double.parseDouble(line.substring(28, 42).trim());
                        continue;
                    }
                    if(line.contains("# / TYPES OF OBSERV")){
                        if (line.trim().length() < 60) {
                            continue;
                        }
                        //观测类型数量
                        obsTypeNum = Integer.parseInt(line.substring(0, 6).trim());
                        String obsType = line.substring(6, 60); // 观测类型
                        //如果观测类型数量超过10
                        if (obsTypeNum >= 10) {
                            line = lines.get(index++);
                            obsType = obsType + line.substring(6, 60);
                        }
                        if (obsTypeNum >= 20) {
                            line = lines.get(index++);
                            obsType = obsType + line.substring(6, 60);
                        }
                        if (obsTypeNum >= 30) {
                            line = lines.get(index++);
                            obsType = obsType + line.substring(6, 60);
                        }
                        if (obsTypeNum >= 40) {
                            line = lines.get(index++);
                            obsType = obsType + line.substring(6, 60);
                        }
                        //根据观测类型判断是否是双频
                        String[] obsTypeArray =new String[obsTypeNum];
                        for (int i = 0; i < obsTypeNum; i++) {
                            obsTypeArray[i] = obsType.substring(i * 6, i * 6 + 6).trim();
                            obsTypeList.add(obsTypeArray[i]);
                        }
                        if (obsTypeList.containsAll(GnssContext.OBS_TYPE_A)||
                                obsTypeList.containsAll(GnssContext.OBS_TYPE_B)) {
                            continue;
                        }
                        return list;
                    }
                    if (line.contains("END OF HEADER")) {
                        break;
                    }
                }
                if (x == 0 || y == 0 || z == 0) {
                    return list;
                }
                double minEle = GnssContext.MIN_FILE;//20.0;
                //获取某时刻所有GPS卫星轨道参数
                Double[][] path = this.getNavPath(navFile, gnssFile, oVersion);
                if (path == null) {
                    return null;
                }
                for (;index<lines.size();index++) {
                    line = lines.get(index);
                    String dateTime = "";
                    int startNum = 0;  //卫星数量
                    List<String> listStart = new ArrayList<>();  //卫星列表
                    if(line.length() > 29){
                        if(line.substring(26, 29).trim().equals("0") || line.substring(26, 29).trim().equals("1")){
                            dateTime = getObsDateTime(line.substring(0, 26), gnssFile.getYear().toString());
                            String tempHour = dateTime.substring(11, 13);
                            if (!StringUtils.isBlank(tempHour) && !tempHour.equalsIgnoreCase(NumberUtils.format(gnssFile.getHoure(),"00"))) {
                                hour = tempHour;
                                //获取周秒
                                weekseconds=this.getWeekSeconds(gnssFile.getDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))+hour+"0000");
                                //获取某时刻所有GPS卫星轨道参数
                                path = this.getNavPath(navFile,gnssFile, oVersion);
                            }
                            if (StringUtils.isBlank(line.substring(29,32).trim())) {
                                return null;
                            }
                            startNum = Integer.parseInt(line.substring(29, 32).trim());
                            int endRow = 0;//卫星号一共有多少行
                            if(startNum%12 == 0){
                                endRow = startNum/12;
                            }else{
                                endRow = startNum/12 + 1;
                            }
                            if(endRow == 1){//只有一行的时候
                                this.readSplitData(listStart,line,1);
                                continue;
                            }
                            for(int j=1; j<=endRow; j++){
                                if(j == 1){//读第一行的时候
                                    this.readSplitData(listStart,line,12);
                                    continue;
                                }//读下一行的时候
                                line = lines.get(index ++);
                                if(j == endRow){//读到最后一行的时候
                                    this.readSplitData(listStart,line,startNum-12*(endRow-1));
                                    continue;
                                }
                                //读中间行的时候
                                this.readSplitData(listStart,line,12);
                            }
                        }
                    }
                    //读C1,P1,P2,L1,L2五个参数
                    if(obsTypeNum <= 5){
                        for(int i=0; i<startNum; i++){
                            line = lines.get(index ++);
                            Map<String, Double> mapStartData = new HashMap<>();
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 0);
                            }

                            Double L1 = mapStartData.get("L1");
                            Double L2 = mapStartData.get("L2");
                            if(L1 == null || L2 == null || L1*L2 == 0){
                                continue;
                            }else{
                                String startName = listStart.get(i);
                                if(startName.contains("G")){
                                    int startID = Integer.parseInt(startName.substring(1, 3).trim());
                                    if(!starList.contains(startID)){
                                        starList.add(startID);
                                    }
                                    String tecpAndTecl = getTecPTecL(mapStartData, dateTime, L1, L2);
                                    if(tecpAndTecl != null){  //当TECP和TECL为空的时候不必要算仰角和方位角
                                        if(path[startID-1][10]== -99999 || path[startID-1][10]==0.0){}else{
                                            // 即阿U三方位角
                                            String aziEle = acculateAzel(path, startID, dateTime, lon, lat, height, x, y, z);
                                            if(aziEle != null){   //为空的时候不必要算仰角和方位角
                                                //时间、卫星号、方位角、仰角、TECP（伪距）、TECL（相位）、L1、L2
                                                if(Double.parseDouble(aziEle.split(",")[1]) >= minEle){
                                                    list.add(dateTime+","+startID+","+aziEle.split(",")[0]+","+aziEle.split(",")[1]+","+tecpAndTecl.split(",")[0]+","+tecpAndTecl.split(",")[1]+","+L1+","+L2);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        continue;
                    }
                    if(obsTypeNum > 5 && obsTypeNum <= 10){
                        for(int i=0; i<startNum; i++){
                            Map<String, Double> mapStartData = new HashMap<String, Double>();
                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 0);
                            }

                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 5);
                            }

                            Double L1 = mapStartData.get("L1");
                            Double L2 = mapStartData.get("L2");
                            if(L1 == null || L2 == null || L1*L2 == 0){
                                continue;
                            }
                            String startName = listStart.get(i);
                            if(startName.contains("G")){
                                String tecpAndTecl = getTecPTecL(mapStartData, dateTime, L1, L2);
                                int startID = Integer.parseInt(startName.substring(1, 3).trim());
                                if(!starList.contains(startID)){
                                    starList.add(startID);
                                }
                                if(tecpAndTecl != null){  //当TECP和TECL为空的时候不必要算仰角和方位角
                                    if(path[startID-1][10]== -99999 || path[startID-1][10]==0.0){}else{
                                        String aziEle = acculateAzel(path, startID, dateTime, lon, lat, height, x, y, z);
                                        if(aziEle != null){   //为空的时候不必要算仰角和方位角
                                            //时间、卫星号、方位角、仰角、TECP（伪距）、TECL（相位）、L1、L2
                                            if(Double.parseDouble(aziEle.split(",")[1]) >= minEle){
                                                list.add(dateTime+","+startID+","+aziEle.split(",")[0]+","+aziEle.split(",")[1]+","+tecpAndTecl.split(",")[0]+","+tecpAndTecl.split(",")[1]+","+L1+","+L2);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        continue;
                    }
                    if(obsTypeNum > 10 && obsTypeNum <= 15){
                        for(int i=0; i<startNum; i++){
                            Map<String, Double> mapStartData = new HashMap<String, Double>();
                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 0);
                            }

                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 5);
                            }

                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 10);
                            }

                            Double L1 = mapStartData.get("L1");
                            Double L2 = mapStartData.get("L2");
                            if(L1 == null || L2 == null || L1*L2 == 0){
                                continue;
                            }else{
                                String startName = listStart.get(i);
                                if(startName.contains("G")){
                                    String tecpAndTecl = getTecPTecL(mapStartData, dateTime, L1, L2);
                                    int startID = Integer.parseInt(startName.substring(1, 3));
                                    if(!starList.contains(startID)){
                                        starList.add(startID);
                                    }
                                    if(tecpAndTecl != null){  //当TECP和TECL为空的时候不必要算仰角和方位角
                                        if(path[startID-1][10]== -99999 || path[startID-1][10]==0.0){}else{
                                            String aziEle = acculateAzel(path, startID, dateTime, lon, lat, height, x, y, z);
                                            if(aziEle != null){   //为空的时候不必要算仰角和方位角
                                                //时间、卫星号、方位角、仰角、TECP（伪距）、TECL（相位）、L1、L2
                                                if(Double.parseDouble(aziEle.split(",")[1]) >= minEle){
                                                    list.add(dateTime+","+startID+","+aziEle.split(",")[0]+","+aziEle.split(",")[1]+","+tecpAndTecl.split(",")[0]+","+tecpAndTecl.split(",")[1]+","+L1+","+L2);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        continue;
                    }
                    if(obsTypeNum > 15 && obsTypeNum <= 20){
                        for(int i=0; i<startNum; i++){
                            Map<String, Double> mapStartData = new HashMap<String, Double>();
                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 0);
                            }

                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 5);
                            }

                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 10);
                            }

                            line = lines.get(index ++);
                            if(line != null){
                                getMap(line, mapStartData, obsTypeList, 15);
                            }

                            Double L1 = mapStartData.get("L1");
                            Double L2 = mapStartData.get("L2");
                            if(L1 == null || L2 == null || L1*L2 == 0){
                                continue;
                            }else{
                                String startName = listStart.get(i);
                                if(startName.contains("G")){
                                    String tecpAndTecl = getTecPTecL(mapStartData, dateTime, L1, L2);
                                    int startID = Integer.parseInt(startName.substring(1, 3).trim());
                                    if(!starList.contains(startID)){
                                        starList.add(startID);
                                    }
                                    if(tecpAndTecl != null){  //当TECP和TECL为空的时候不必要算仰角和方位角
                                        if(path[startID-1][10]== -99999 || path[startID-1][10]==0.0){}else{
                                            String aziEle = acculateAzel(path, startID, dateTime, lon, lat, height, x, y, z);
                                            if(aziEle != null){   //为空的时候不必要算仰角和方位角
                                                //时间、卫星号、方位角、仰角、TECP、TECL、L1、L2
                                                if(Double.parseDouble(aziEle.split(",")[1]) >= minEle){
                                                    list.add(dateTime+","+startID+","+aziEle.split(",")[0]+","+aziEle.split(",")[1]+","+tecpAndTecl.split(",")[0]+","+tecpAndTecl.split(",")[1]+","+L1+","+L2);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("o文件合并失败：" + e.toString(), e);
        }
        return list;
    }

    /**
     * 读取行数据
     *
     * @param listStart
     * @param line
     * @param max
     */
    private void readSplitData(List<String> listStart, String line, int max){
        if (StringUtils.isBlank(line)) {
            return;
        }
        for (int i = 0; i < max; i++) {
            try {
                listStart.add(line.substring(32+i*3, 32+(i+1)*3).trim());
            } catch (Exception e) {
                continue;
            }
        }
    }

    /**
     * 读取N文件获取轨道参数
     *
     * @param navFile
     * @param gnssFile
     * @param oVersion
     * @return
     * @author July july_sky@foxmail.com
     * @date 2019/4/29 22:32
     */
    public Double[][] getNavPath(Path navFile, GnssFile gnssFile, String oVersion) {
        Double[][] path = new Double[32][31];
        for (int i = 0; i < path.length; i++) {
            for (int j = 0; j < path[1].length; j++) {
                path[i][j] = -99999D;
            }
        }
        String staNum = null; // 卫星号
        String date = null; // 导航时间
        String line = "";
        try {
            List<String> lines = Files.readAllLines(navFile);
            int i = 0;
            for (; i < lines.size(); i ++) {
                if (lines.get(i).contains("END OF HEADER")) {
                    break;
                }
            }
            for (;i < lines.size(); i++) {
                line = lines.get(i);
                staNum = line.substring(0, 2).trim(); // 卫星号
                if (StringUtils.isBlank(staNum)) {
                    continue;
                }
                date = line.substring(2, 22); // 导航时间
                if (StringUtils.isBlank(date)) {
                    return null;
                }
                date = this.getNavDateTime(date, gnssFile.getYear().toString());
                if (StringUtils.isBlank(date)) {
                    return null;
                }
                i = this.readPathData(lines, i, path, NumberUtils.toInt(staNum)-1, this.getWeekSeconds(gnssFile.getDateStr()));
                if (i == -1) {
                    return path;
                }
            }
        } catch (IOException e) {
            log.error("N文件解析失败",e);
        }
        return path;
    }

    /**
     * 读取轨道数据
     *
     * @param lines 所有行
     * @param rowIndex 当前行索引
     * @param path 数据
     * @param staNum 卫星号
     * @return
     */
    private int readPathData(List<String> lines, int rowIndex, Double[][] path, int staNum, int weekseconds){
        String line = lines.get(rowIndex);
        String afLine = line.replaceAll("D","E");
        double[] tempPath = new double[31];
        tempPath[0] = NumberUtils.toDouble(afLine.substring(22,41).trim()); //钟偏
        tempPath[1] = NumberUtils.toDouble(afLine.substring(41,60).trim()); //钟漂
        tempPath[2] = NumberUtils.toDouble(afLine.substring(60,79).trim()); //钟漂率
        // 导航参数

        rowIndex ++;
        //数组下标：卫星号减1，即1号卫星在数组中对应的下标是0
        for (int i = 0; i < 7; i++) {
            line = lines.get(rowIndex);
            if (StringUtils.isBlank(line)) {
                continue;
            }
            for (int j = 0; j < 4; j++) {
                int lenght = line.length();
                if (19 * j + 3 >= lenght) {
                    continue;
                }
                if (lenght < 19 * j + 22) {
                    return -1;
                }
                String temp = line.substring(19 * j + 3, 19 * j + 22).trim();
                if (StringUtils.isBlank(temp)) {
                    continue;
                }
                tempPath[i * 4 + j + 3] =  Double.parseDouble(temp.replace('D', 'E'));
            }
            rowIndex ++;
        }
        if (path[staNum][11].doubleValue() == -99999) {
            this.copyAll(path, tempPath, staNum);
            return rowIndex;
        }
        //当path中已经存了某个时次的轨道参数时，需要判断该时次是不是最近时次
        double differ1 = Math.abs(path[staNum][11] - weekseconds);
        if (differ1 > 302400) {
            differ1 = Math.abs(differ1 - 604800);
        }
        double differ2 = Math.abs(tempPath[11] - weekseconds);
        if (differ2 > 302400) {
            differ2 = Math.abs(differ2 - 604800);
        }
        if(differ2 >= differ1){
            return rowIndex;
        }
        this.copyAll(path, tempPath, staNum);
        return rowIndex;
    }

    private void copyAll(Double[][] path,double[] temp,int staNum){
        for (int i=0;i<temp.length;i++) {
            path[staNum][i] = temp[i];
        }
    }
    /**
     * 获取周秒
     *
     * @param date
     * @return
     */
    private Integer getWeekSeconds(String date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateFormatUtils.parse(date,"yyyyMMddHHmmss"));
        int days = calendar.get(Calendar.DAY_OF_WEEK);
        return (days - 1) * 24 * 60 * 60 + calendar.get(Calendar.HOUR_OF_DAY) * 60 * 60 + calendar.get(Calendar.MINUTE) * 60 + calendar.get(Calendar.SECOND);
    }

    /**
     * 格式化N文件日期
     *
     * @param date
     * @param year
     * @return
     */
    private String getNavDateTime(String date,String year) {
        String yyyy = date.substring(0,3).trim();
        String MM = date.substring(3,6).trim();
        String d = date.substring(6,9).trim();
        String h = date.substring(9,12).trim();
        String m = date.substring(12, 15).trim();
        String s = date.substring(15, 20).trim();
        return formatDate(yyyy,MM,d,h,m,s,year);
    }

    /**
     * 格式化O文件日期
     *
     * @param Date
     * @param year
     * @return
     */
    public String getObsDateTime(String Date,String year){
        String yyyy = Date.substring(0,3).trim();
        String MM = Date.substring(3,6).trim();
        String d = Date.substring(6,9).trim();
        String h = Date.substring(9,12).trim();
        String m = Date.substring(12,15).trim();
        String s = Date.substring(15,26).trim();
        return formatDate(yyyy,MM,d,h,m,s,year);
    }

    /**
     * 日期格式验证
     *
     * @param yyyy 文件年
     * @param MM 月
     * @param d 日
     * @param h 时
     * @param m 分
     * @param s 秒
     * @param year 实际年
     * @return
     */
    private String formatDate(String yyyy,String MM,String d,String h,String m,String s,String year) {
        if (yyyy.length() == 1) {
            yyyy = year.substring(0,2)+"0" + yyyy;
        }else if(yyyy.length() == 2){
            yyyy = year.substring(0,2) + yyyy;
        }
        s = ((int )Math.round(Double.parseDouble(s)))+"";
        String dt = yyyy+"-"+MM+"-"+d+" "+h+":"+m+":"+s;
        if (DateUtils.isDate(dt, "yyyy-MM-dd HH:mm:ss")) {
            return dt;
        }
        return null;
    }

    /**
     * 读取每颗卫星每条记录的观测文件的数据
     * @author July july_sky@foxmail.com
     * @date 2019/4/30 0:45
     * @param line 文件每行的数据
     * @param mapStartData 存放每颗卫星每条记录的观测文件的数据
     * @param obsType 观测文件要观测的类型列表
     * @param num 要保存的位置
     * @return
     */
    public Map<String, Double> getMap(String line, Map<String, Double> mapStartData, List<String> obsType, int num){
        if (line.length() >= 78) {
            mapStartData.put(obsType.get(num+4),this.getMapValue(line, 64,78));
        }
        if (line.length() >= 62) {
            mapStartData.put(obsType.get(num+3),this.getMapValue(line, 48,62));
        }
        if (line.length() >= 46) {
            mapStartData.put(obsType.get(num+2),this.getMapValue(line, 32,46));
        }
        if (line.length() >= 30) {
            mapStartData.put(obsType.get(num+1),this.getMapValue(line, 16,30));
        }
        if (line.length() >= 14) {
            mapStartData.put(obsType.get(num),this.getMapValue(line, 0,14));
        }
        return mapStartData;
    }

    private Double getMapValue(String line,int start,int end) {
        return StringUtils.isBlank(line.substring(start, end).trim()) ? 0D : NumberUtils.toDouble(line.substring(start, end).trim());
    }

    /**
     * 计算TECP和TECL
     * @author July july_sky@foxmail.com
     * @date 2019/4/30 0:48
     * @param hm 每颗卫星每条记录的观测文件的数据
     * @param dateTime 时间
     * @param l1 观测类型L1的值
     * @param l2 观测类型L2的值
     * @return
     */
    public String getTecPTecL(Map<String, Double> hm, String dateTime, Double l1, Double l2){
        //计算TECP和 TECL，此处用了C1,P1,P2和L1,L2五个参数
        double c1 = StringUtils.isBlank(hm.get("C1")) ? 0 : hm.get("C1"),
                p1 = StringUtils.isBlank(hm.get("P1")) ? 0 : hm.get("P1"),
                p2 = StringUtils.isBlank(hm.get("P2")) ? 0 : hm.get("P2");
        double tecl=0.0,tecp=0.0;
        try {
//            double Cspeed = GnssContext.CSPEED;//2.99792458e+8; //光速:米/秒
//            double f1 = GnssContext.F1;//154.e0*10.23e+6;
//            double f2 = GnssContext.F2;//120.e0*10.23e+6;
            if (l1 == 0 || l2 == 0) {
                return null;
            }
            tecl = (GnssContext.CSPEED * l2 / GnssContext.F2 - GnssContext.CSPEED * l1 / GnssContext.F1) / 40.28e0 / (1.e0 / GnssContext.F1 / GnssContext.F1 - 1.e0 / GnssContext.F2 / GnssContext.F2) / 1.e16;
            tecl = tecl % 1000.0;
            if (p1 * p2 != 0) { // TECP == P1*P2
                tecp = (p1 - p2) / 40.28e0 / (1.e0 / GnssContext.F1 / GnssContext.F1 - 1.e0 / GnssContext.F2 / GnssContext.F2) / 1.e16;
                tecp = tecp % 1000.0;
            } else {
                if (c1 == 0 || p2 == 0) {
                    return null;
                }
                tecp = (c1 - p2) / 40.28e0 / (1.e0 / GnssContext.F1 / GnssContext.F1 - 1.e0 / GnssContext.F2 / GnssContext.F2) / 1.e16;
                tecp = tecp % 1000.0;
            }
            //保留2位小数
            tecl = Double.valueOf(new DecimalFormat("0.00").format(tecl));
            tecp = Double.valueOf(new DecimalFormat("0.00").format(tecp));
            //站名、卫星号、时间、周秒、方位角、仰角、TECP（伪距）、TECL（相位）、L1、L2
            return tecp + "," + tecp;
        } catch (Exception e) {
            log.error("仰角计算失败",e);
            return null;
        }
    }
    /**
     * 计算仰角 方位角
     * @author July july_sky@foxmail.com
     * @date 2019/4/30 0:58
     * @param path 轨道参数
     * @param staId 卫星号
     * @param time 时间
     * @param lon 经度
     * @param lat 纬度
     * @param height 高度
     * @param X0 x
     * @param Y0 y
     * @param Z0 z
     * @return
     */
    private String acculateAzel(Double[][] path, int staId, String time, double lon, double lat, double height, double X0, double Y0, double Z0) {
        try {
            //地球引力常数GM = 3986005e8 m3/s2
            double GM = 3986005e8;
            //地球椭球长半径a=6378137 m
            //double a = 6378137;
            //地球自转角速度 wo=7292115×10-11 rad/s
            double wo = 7292115e-11;

            //获取周秒
            int weekSec = this.getWeekSeconds(time);
            //获取卫星数组下标
            int satNum = staId - 1;

            double n0, n, tk, mk, ek, vk, phik, uk, rk, ik, omegak;
            //（1）计算卫星运行的平均角速度n
            n0 = Math.sqrt(GM / Math.pow(path[satNum][10] * path[satNum][10], 3));//sqrt(A)
            n = n0 + path[satNum][5];//摄动改正项:Delta n (弧度/秒)

            //（2）计算归化观测时间tk     tk=t-toe
            //其中t为电文中给出的观测时刻，toe为电文中给出的参考时刻。
            tk = weekSec - path[satNum][11];//toe GPS周积秒
            if (tk > 302400) {
                tk = tk - 604800;
            } else if (tk < -302400) {
                tk = tk + 604800;
            }

            //（3）计算观测时刻的卫星平近点角mk    Mk＝M0＋ntk
            //其中M0为电文中给出的参考时刻toe的平近点角。
            mk = path[satNum][6] + n * tk;//M0

            //（4）计算偏近点角Ek  Ek＝Mk＋e*sinEk
            //其中e为电文中给出的GPS轨道偏心率，Ek通过初始值Ek＝Mk，迭代两次获得
//					ek = mk;
//					ek = mk + path[satNum][8] * Math.sin(ek);//e
//					ek = mk + path[satNum][8] * Math.sin(ek);//e
            double ek1, ek2, error = 1e-12;
            ek1 = mk;
            do {
                ek2 = mk + path[satNum][8] * Math.sin(ek1);
                if (Math.abs(ek2 - ek1) <= error)
                    break;
                ek1 = ek2;
            } while (true);
            ek = ek1;
            //（5）计算真近点角Vk
            vk = getAtan(Math.cos(ek) - path[satNum][8], Math.sqrt(1.0 - path[satNum][8] * path[satNum][8]) * Math.sin(ek));//e

            //（6）计算升交距角
            //其中ω为电文中给出的近地点角距 omega
            phik = vk + path[satNum][17];//ω : omega

            //（7）计算摄动改正项
            double deltau = path[satNum][7] * Math.cos(2.0 * phik) + path[satNum][9] * Math.sin(2.0 * phik);
            double deltar = path[satNum][16] * Math.cos(2.0 * phik) + path[satNum][4] * Math.sin(2.0 * phik);
            double deltai = path[satNum][12] * Math.cos(2.0 * phik) + path[satNum][14] * Math.sin(2.0 * phik);

            //（8）计算经过摄动改正的升交距角uk、卫星矢径rk和轨道倾角ik
            uk = phik + deltau;
            rk = path[satNum][10] * path[satNum][10] * (1 - path[satNum][8] * Math.cos(ek)) + deltar;//sqrt(A)  sqrt(A)  e
            ik = path[satNum][15] + deltai + path[satNum][19] * tk;

            @SuppressWarnings("unused")
            double XK, YK, ZK, xk, yk, zk;
            //（9）计算卫星在轨道平面坐标系的坐标 xk, yk, zk
            xk = rk * Math.cos(uk);
            yk = rk * Math.sin(uk);
            zk = 0;

            //（10）计算观测时刻升交点经度
            omegak = path[satNum][13] + (path[satNum][18] - wo) * tk - wo * path[satNum][11];//OMEGA   OMEGA_DOT   toeGPS周积秒
            XK = xk * Math.cos(omegak) - yk * Math.cos(ik) * Math.sin(omegak);
            YK = xk * Math.sin(omegak) + yk * Math.cos(ik) * Math.cos(omegak);
            ZK = yk * Math.sin(ik);

			/*
			先读取星历文件，然后按照公式2.3～2.13，计算出（11）中的Xk，Yk，Zk，
			在从观测文件的头文件中读取出XYZ，并转换为L B H 后,
			带入公式（2.15 2.16）就能计算出仰角和方位角了
			*/

            //（1）计算观测站在WGS-84大地坐标系下的坐标
            //L、B和H分别是观测站在大地坐标系中的经度、纬度和高程
            if (height < 0) height = 0;
            double L = lon * Math.PI / 180;
            double B = lat * Math.PI / 180;
            double H = height;

            double a = 6378137;//地球半径
            double e2 = 0.0818;//第一偏心率
            double N = a / Math.sqrt(1.0 - e2 * e2 * Math.sin(B) * Math.sin(B));//N为该点卯酉圈曲率半径

            //（2）卫星在WGS-84坐标系下的空间直角坐标XK，YK和ZK,表示为站心地平直角坐标系中直角坐标x、y和z
            X0 = (N + H) * Math.cos(B) * Math.cos(L);
            Y0 = (N + H) * Math.cos(B) * Math.sin(L);
            Z0 = (N * (1.0 - e2 * e2) + H) * Math.sin(B);

            double DeltaX = XK - X0;
            double DeltaY = YK - Y0;
            double DeltaZ = ZK - Z0;

            double x = -Math.sin(B) * Math.cos(L) * DeltaX - Math.sin(B) * Math.sin(L) * DeltaY + Math.cos(B) * DeltaZ;
            double y = -Math.sin(L) * DeltaX + Math.cos(L) * DeltaY;
            double z = Math.cos(B) * Math.cos(L) * DeltaX + Math.cos(B) * Math.sin(L) * DeltaY + Math.sin(B) * DeltaZ;

            //（3）计算观测站相对于卫星的距离r、仰角E0和方位角AZ
            //方位角
            double azi = getAtan(x, y) * 180.0 / Math.PI;
            //仰角
            double ele = getAtan(Math.sqrt(x * x + y * y), z) * 180.0 / Math.PI;
            if (ele > 90) {
                ele = ele - 360;
            }

            //保留2位小数
            azi = Double.valueOf(new DecimalFormat("0.00").format(azi));
            ele = Double.valueOf(new DecimalFormat("0.00").format(ele));
            //System.out.print("   方位角="+azi+"    仰角="+ele);
            return azi + "," + ele;
        } catch (Exception e) {
           log.error("仰角计算失败",e);
            return null;
        }
    }

    private double getAtan(double z, double y) {
        if (z == 0) {
            return 0;
        }
        if (y == 0) {
            return Math.PI;
        }
        double x = Math.atan(Math.abs(y / z));
        if (y > 0 && z < 0) {
            return Math.PI - x;
        }
        if (y < 0 && x < 0) {
            return Math.PI - x;
        }
        if (y <0 && z > 0) {
            return Math.PI * 2 - x;
        }
        return 0;
    }
}
